﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using Innovox.NetTools;
using Innovox.YDeviceLib;
using System.IO;
using System.Net;
using System.Xml;
using System.Xml.XPath;
using System.Net.Sockets;
//using System.Windows.Data.DataSourceProvider;

namespace TestConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            /*
             * INFO_QUERY
================
SRCMAC(6bytes)
DSTMAC(6bytes) => PLC Node
000E AAAA 0300 139D
TYPE = 0xA5
SUB-TYPE = 0xAA
*/

            UdpClient udpClient = new UdpClient(40004);
            //udpClient.EnableBroadcast = true;
            try
            {
                IPAddress ip = IPAddress.Parse("192.168.192.60");
                IPEndPoint endPoint = new IPEndPoint(ip, 40004);
                udpClient.Connect(endPoint);
                //udpClient.Close();
                //Console.ReadLine();
                // Sends a message to the host to which you have connected.
                //Byte[] sendBytes = Encoding.ASCII.GetBytes("Is anybody there?");
                //Byte[] sendBytes = new Byte[] { 0x00, 0x07, 0xe9, 0x5e, 0x4b, 0xa2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x08, 0xaa, 0xaa, 0x03, 0x00, 0x13, 0x9d, 0x0c, 0x01 };
                Byte[] sendBytes = new Byte[] { 0xa2, 0x4b, 0x5e, 0xe9, 0x07, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x08, 0x00, 0x03, 0xaa, 0xaa, 0x9d, 0x13, 0x00, 0x0c, 0x01 };
                //Byte[] sendBytes = new Byte[] { 0xa2, 0x4b, 0x5e, 0xe9, 0x07, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x08, 0xaa, 0xaa, 0x03, 0x00, 0x13, 0x9d, 0x0c, 0x01 };
                udpClient.Send(sendBytes, sendBytes.Length);

                IPEndPoint receiveEndPoint = new IPEndPoint(ip, 40004);
                byte[] receiveBytes = udpClient.Receive(ref receiveEndPoint);
                string returnData = Encoding.ASCII.GetString(receiveBytes);



                Console.ReadLine();
                int count = udpClient.Available;
                udpClient.Close();
                return;
                /*
                // Sends a message to a different host using optional hostname and port parameters.
                UdpClient udpClientB = new UdpClient();
                udpClientB.Send(sendBytes, sendBytes.Length, "AlternateHostMachineName", 11000);

                //IPEndPoint object will allow us to read datagrams sent from any source.
                IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);
                */
                // Blocks until a message returns on this socket from a remote host.
                //Byte[] receiveBytes = udpClient.Receive(ref RemoteIpEndPoint);
               /* string returnData = Encoding.ASCII.GetString(receiveBytes);

                // Uses the IPEndPoint object to determine which of these two hosts responded.
                Console.WriteLine("This is the message you received " +
                                             returnData.ToString());
                Console.WriteLine("This message was sent from " +
                                            RemoteIpEndPoint.Address.ToString() +
                                            " on their port number " +
                                            RemoteIpEndPoint.Port.ToString());

                udpClient.Close();
                udpClientB.Close();*/

            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }


            Console.ReadLine();
        }

        void TestObix()
        {
           try
            {/*
                ObixServerAmbassador obixServer = new ObixServerAmbassador("http://192.168.192.165:40044/obix/");
                obixServer.WriteAttributeValue("/obix/y1g/ledDim", "50");
                string swStatus = obixServer.GetAttributeValue("/obix/y1g/ledDim");
                //string swStatus = obixServer.GetAttributeValue("str", "name");
                Console.WriteLine(swStatus);
                while (true)
                {
                    try
                    {
                        obixServer.OpenBatch();
                        obixServer.AddReadToBatch("/obix/y1g/ledDim");
                        obixServer.CloseBatch();
                        obixServer.SendBatch();
                    }
                    catch
                    {

                    }
                }*/
                //Console.WriteLine(obixServer.ToString());
                /*
                HttpRequest request = new HttpRequest("http://192.168.1.105:40044/obix/");
                //HttpRequest request = new HttpRequest("http://192.168.1.105:40044/obix/batch/");
                //string body = "<list of=\"obix:uri\" is=\"obix:BatchIn\">\r\n<uri is=\"obix:Read\" val=\"/obix/firmwareVersion/\"/>\r\n<uri is=\"obix:Read\" val=\"/obix/about/serverName/\"/>\r\n<uri is=\"obix:Read\" val=\"/obix/name/\"/>\r\n<uri is=\"obix:Read\" val=\"/obix/location/\"/>\r\n</list>\r\n";
                //request.Post(body);
                request.Get();
                string resp = request.ResponseToString()+"\r\n";
                Console.WriteLine(resp);*/
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
            Console.ReadLine();
        }
    }

    public class ObixServerAmbassador
    {
        string lobbyUrl;
        XmlDocument xmlDoc;
        string BatchBody;
        string BatchUrl;

        public ObixServerAmbassador(string lobbyUrl)
        {
            this.lobbyUrl = lobbyUrl;
            xmlDoc = GetDocument(lobbyUrl);

            XmlElement lobby = xmlDoc.DocumentElement;
            AddRefElementChilds(lobbyUrl, lobby);
        }

        public void OpenBatch()
        {
            BatchUrl = lobbyUrl + "batch/";
            BatchBody = "<list of=\"obix:uri\" is=\"obix:BatchIn\">\r\n";
        }

        public void AddReadToBatch(string uri)
        {
            BatchBody += "<uri is=\"obix:Read\" ";
            BatchBody += "val=\"" + uri + "\"/>\r\n";
        }

        public void AddWriteToBatch(string uri, string type, string val)
        {
            BatchBody += "<uri is=\"obix:Write\" ";
            BatchBody += "val=\"" + uri + "\">\r\n";
            BatchBody += "<" + type + " name=\"in\" val=\"" + val + "\" />\r\n</uri>\r\n";
        }

        public void CloseBatch()
        {
            BatchBody += "</list>\r\n";
        }

        public void SendBatch()
        {
            
            HttpRequest request = new HttpRequest(BatchUrl);
            request.Post(BatchBody);
            string resp = request.ResponseToString() + "\r\n";
            Console.WriteLine(resp);
        }

        private void AddRefElementChilds(string url, XmlNode hrefNode)
        {
            //XmlElement lobby = xmlDoc.DocumentElement;
            foreach (XmlNode childNode in hrefNode.ChildNodes)
            {
                if (childNode.Name == "ref")
                {
                    string elementRef = childNode.Attributes["href"].Value;
                    string childUrl = url + elementRef;
                    XmlDocument childDoc = GetDocument(childUrl);
                    XmlElement firstElement = childDoc.DocumentElement;
                    firstElement.Attributes["href"].Value = childUrl;
                  
                    foreach (XmlNode newNode in firstElement.ChildNodes)
                    {
                        childNode.AppendChild(xmlDoc.ImportNode(newNode, true));
                        AddRefElementChilds(childUrl, childNode);
                    }
                }
            }
        }

        private XmlDocument GetDocument(string uri)
        {
            HttpRequest request = new HttpRequest(uri);
            request.Get();
            string resp = request.ResponseToString() + "\r\n";
            Console.WriteLine(resp);

            byte[] byteArray = Encoding.UTF8.GetBytes(resp);
            MemoryStream stream = new MemoryStream(byteArray);

            XmlDocument doc = new XmlDocument();
            doc.Load(stream);
            return doc;
        }

        public string GetAttributeValue(string relativePath)
        {
            XmlNode selectedNode = SelectNode(relativePath);
            return selectedNode.Attributes["val"].Value;
        }

        public void WriteAttributeValue(string relativePath, string value)
        {
            XmlNode selectedNode = SelectNode(relativePath);
            selectedNode.Attributes["val"].Value = value;
        }

        private XmlNode SelectNode(string relativePath)
        {
            string xpathExpression = BuildXPathExpressionFromObixPath(relativePath);
            XmlElement lobby = xmlDoc.DocumentElement;
            XmlNode selectedNode = lobby.SelectSingleNode(xpathExpression);
            return selectedNode;    
        }

        private string BuildXPathExpressionFromObixPath(string path)
        {
            string[] hrefList = path.Split('/');
            string xpathExpression = "";
            foreach (string href in hrefList)
            {
                if (href == "obix")
                    xpathExpression += "//*[@is='obix:Lobby']";
                else if (href != "")
                    xpathExpression += "/*[@name='" + href + "']";
            }
            return xpathExpression;
        }
    }

    public class Test
    {
        Y1G _device;
        YNetManager _yNet;

        public Test()
        {
            _device = null;
            _yNet = new YNetManager();
        }

        public void ScanWorker_DoWork()
        {
            PingRange pr = new PingRange("192.168.1.105", "192.168.1.106");

            _device = null;

            _yNet.Scan(pr.StartRange.ToString(), pr.EndRange.ToString());

            foreach (KeyValuePair<IPAddress, YDevice> kvp in _yNet.Devices)
            {
                if (kvp.Value.Modem.AccesType == ModemAccessType.Node)
                {
                    _device = (Y1G) kvp.Value;
                    Console.WriteLine("Device found: " + _device.Ip.ToString());
                }
            }

            if (_device == null)
            {
                Console.WriteLine("No Device found");
            }
        }

        public void TestWorker_DoWork()
        {
            while (_device != null)
            {
                Thread.Sleep(200);
                _device.RefreshProperties();
            }
        }
    }
}
